#include <iostream>
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <typeinfo>
using namespace std;
#define mp_arglist  template
#define mp_arg      typename
#define mp_data     typedef
#define mp_function struct


#define mp_return(T)    mp_data T type
#define mp_exec(Func)   Func::type
#define mp_eval(Func)   Func::value

template<int N, int M>
struct meta_func
{
    static const int value = N + M;
};

mp_arglist<int L, int R>
mp_function static_min
{
    static const int value = (L < R) ? L:R;
};

mp_arglist<mp_arg T1, mp_arg T2>
mp_function select1st
{
    mp_return (T1);
};
constexpr int b1 = 4;
constexpr int b2 = 6;
constexpr int b3 = b1 + b2;

template <class T, T val>
struct integral_constant_my
{
    typedef T   value_type;
    typedef integral_constant_my<T, val>  type;
    static const T  value = val;
};

typedef integral_constant_my<bool, true>        true_type_my;
typedef integral_constant_my<bool, false>       false_type_my;

template <class T, T val>
struct float_constant_my
{

    typedef float_constant_my<T, val>   type;
    typedef T                           value_type;
    static const T                      value = val;
};

void meta_main()
{
    cout << meta_func<10,10>::value << endl;
    cout << static_min<20,10>::value <<endl;
    cout << static_min<b1,b2>::value <<endl;
    cout << static_min<b2,b3>::value <<endl;
    logInfo("min=%d",static_min<20,10>::value );
   // logInfo("min=%d",mp_eval() static_min<20,10>::value );
    constexpr int a1 = 4;
    constexpr double a2 = 4.5;
    select1st< decltype(a1), decltype(a2)>::type a = 10.3;
  //  mp_exec( select1st<int,double> ) b = 4.5;
    cout <<a<<endl;
///    cout << "is "<<is_integral<int>::type;
   auto c1 = mp_eval(is_integral<int>);
   bool c2 = mp_eval(is_integral<int>);
   auto c3 = is_integral<int>::value;
   cout << c1 <<endl;

   char d[2][4][12]= {};
   cout <<
   logInfo("a vecotr=%d", rank<decltype(d)>::value);

   logInfo("integral_constant_my=%d", integral_constant_my<int, 40>::value);
   logInfo("integral_constant_my=%f", integral_constant_my<int, 43>::value);
   cout <<"inter=" << float_constant_my<bool, 43>::value;
   cout <<"true=" <<true_type::value;
   cout <<"false=" <<false_type::value;
}
